﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Nirvana
{
    /// <summary>
    /// 根据不同的品质等级，修改粒子数量
    /// </summary>
    [RequireComponent(typeof(ParticleSystem))]
    public class QualityMaxParticlesControl : MonoBehaviour
    {
        [Serializable]
        public struct ControlItem
        {
            /// <summary>
            /// 粒子最大数量，控制减少内存占用
            /// </summary>
            [Tooltip("粒子最大数量，控制减少内存占用")]
            public int Target;
            /// <summary>
            /// 每帧粒子发射数
            /// </summary>
            [Tooltip("每帧粒子发射数，控制减少GPU渲染性能")]
            public ParticleSystem.MinMaxCurve EmissionRateOverTime;

            /// <summary>
            /// 笔刷数组
            /// </summary>
            public QualityBurst[] Bursts;
            /// <summary>
            /// 控制对象在哪个品质等级显示
            /// </summary>
            [Tooltip("控制在那个品质等级下参数有效")]
            public bool[] EnabledLevels;
        }

        [Serializable]
        public struct QualityBurst
        {
            public float time;
            public ParticleSystem.MinMaxCurve countCurve;
            public int cycleCount;
            public float repeatInterval;
            public float probability;
        }


        [SerializeField]
        [Tooltip("The quality control items.")]
        private ControlItem[] controls;

        private LinkedListNode<Action> onQualityChangedNode; //品质切换回调事件
        private ParticleSystem ps;
        private int defaultMaxParticles = 0;
        private ParticleSystem.MinMaxCurve defaultEmissionRateOverTime;
        private ParticleSystem.Burst[] defaultBursts;
        private void Awake()
        {
            this.ps = this.GetComponent<ParticleSystem>();
            this.defaultMaxParticles = this.ps.main.maxParticles;
            this.defaultEmissionRateOverTime = this.ps.emission.rateOverTime;
            if (this.ps.emission.burstCount > 0)
            {
                this.defaultBursts = new ParticleSystem.Burst[this.ps.emission.burstCount];
                this.ps.emission.GetBursts(this.defaultBursts);
            }

        }

        private void OnEnable()
        {
            onQualityChangedNode = QualityConfig.ListenQualityChanged(this.OnQualityLevelChanged);
            this.OnQualityLevelChanged();
        }
        private void OnDisable()
        {
            if (this.onQualityChangedNode != null)
            {
                QualityConfig.UnlistenQualtiy(this.onQualityChangedNode);
                this.onQualityChangedNode = null;
            }
        }
        private void OnDestroy()
        {
            if (this.onQualityChangedNode != null)
            {
                QualityConfig.UnlistenQualtiy(this.onQualityChangedNode);
                this.onQualityChangedNode = null;
            }
        }

#if UNITY_EDITOR
        private void Reset()
        {

            if (this.controls == null || this.controls.Length == 0)
            {
                var item = new ControlItem();
                item.Target = 0;
                item.EmissionRateOverTime = 0f;
                item.EnabledLevels = new bool[] { false, true};
                this.controls = new ControlItem[] { item };
            }
        }

        public void SetQualityLevel(int level)
        {
            if (this.ps == null)
            {
                this.ps = this.GetComponent<ParticleSystem>();
                this.defaultMaxParticles = this.ps.main.maxParticles;
                this.defaultEmissionRateOverTime = this.ps.emission.rateOverTime;
                if (this.ps.emission.burstCount > 0)
                {
                    this.defaultBursts = new ParticleSystem.Burst[this.ps.emission.burstCount];
                    this.ps.emission.GetBursts(this.defaultBursts);
                }
            }
            bool isSet = false;
            foreach (var ctrl in controls)
            {
                bool _enabled = false;
                if (level < ctrl.EnabledLevels.Length)
                {
                    _enabled = ctrl.EnabledLevels[level];
                }
                if (ctrl.Target > 0 && _enabled)
                {
                    var main = ps.main;
                    main.maxParticles = ctrl.Target;
                    var emission = ps.emission;
                    emission.rateOverTime = ctrl.EmissionRateOverTime;

                    if (ctrl.Bursts != null && ctrl.Bursts.Length > 0)
                    {
                        ParticleSystem.Burst[] bursts = new ParticleSystem.Burst[ctrl.Bursts.Length];
                        for (int i = 0; i < ctrl.Bursts.Length; i++)
                        {
                            var b = ctrl.Bursts[i];
                            var burst = new ParticleSystem.Burst();
                            burst.time = b.time;
                            burst.cycleCount = b.cycleCount;
                            burst.repeatInterval = b.repeatInterval;
                            burst.probability = b.probability;
                            burst.count = b.countCurve;
                            bursts[i] = burst;
                        }
                        emission.SetBursts(bursts);
                    }
                    isSet = true;
                    break;
                }
            }

            //未设置时
            if (!isSet)
            {
                var main = ps.main;
                if (main.maxParticles != defaultMaxParticles) main.maxParticles = defaultMaxParticles;
                var emission = ps.emission;
                emission.rateOverTime = this.defaultEmissionRateOverTime;
                if (this.defaultBursts != null && this.defaultBursts.Length > 0)
                {
                    emission.SetBursts(this.defaultBursts);
                }
                else
                {
                    emission.burstCount = 0;
                }
            }
        }

#endif

        private void OnQualityLevelChanged()
        {
            var level = QualityConfig.QualityLevel;
            bool isSet = false;

            foreach (var ctrl in controls)
            {
                bool _enabled = false;
                if (level < ctrl.EnabledLevels.Length)
                {
                    _enabled = ctrl.EnabledLevels[level];
                }

                if (ctrl.Target > 0 && _enabled)
                {
                    var main = ps.main;
                    main.maxParticles = ctrl.Target;
                    var emission = ps.emission;
                    emission.rateOverTime = ctrl.EmissionRateOverTime;
                    if (ctrl.Bursts != null && ctrl.Bursts.Length > 0)
                    {
                        ParticleSystem.Burst[] bursts = new ParticleSystem.Burst[ctrl.Bursts.Length];
                        for (int i = 0; i < ctrl.Bursts.Length; i++)
                        {
                            var b = ctrl.Bursts[i];
                            var burst = new ParticleSystem.Burst();
                            burst.time = b.time;
                            burst.cycleCount = b.cycleCount;
                            burst.repeatInterval = b.repeatInterval;
                            burst.probability = b.probability;
                            burst.count = b.countCurve;
                            bursts[i] = burst;
                        }
                        emission.SetBursts(bursts);
                    }
                    isSet = true;
                    break;
                }
            }

            //未设置时
            if (!isSet)
            {
                var main = ps.main;
                if (main.maxParticles != defaultMaxParticles) main.maxParticles = defaultMaxParticles;
                var emission = ps.emission;
                emission.rateOverTime = this.defaultEmissionRateOverTime;
                if (this.defaultBursts != null && this.defaultBursts.Length > 0)
                {
                    emission.SetBursts(this.defaultBursts);
                }
                else
                {
                    emission.burstCount = 0;
                }
            }
        }

    }
}

